﻿using System;
using System.Collections.Generic;
using System.Text;

namespace RuyeeModbus
{
    public class ModbusTcpSlave
    {

        public delegate void TransactionCompleteDelegate(ModbusTCPTransaction Transaction);
        /// <summary>
        /// xxxx
        /// </summary>
        public event TransactionCompleteDelegate TransactionCompleteEvent;


        public delegate void SendErroHandler();
        public event SendErroHandler SendErroEvent;

        SocketAsyncClient SocketClinet;
        string remoteServerIP;
        /// <summary>
        /// 远程Modbus服务器IP
        /// </summary>
        public string RemoteServerIP
        {
            get { return remoteServerIP; }
            set { remoteServerIP = value; }
        }


        private bool connected;

        public bool Connected
        {
            get { return SocketClinet.Connected; }
        }

        public void Connect(string serverIP)
        {

            RemoteServerIP = serverIP;
            SocketClinet = new SocketAsyncClient(RemoteServerIP, 502);
            SocketClinet.ReceiveMSGEvent += new SocketAsyncClient.ReceiveMSGHandler(sac_ReceiveMSGEvent);
            SocketClinet.SendErroEvent += new SocketAsyncClient.SendErroHandler(SocketClinet_SendErroEvent);
            SocketClinet.connect();

        }

        void SocketClinet_SendErroEvent()
        {
            SendErroEvent();
        }


        void sac_ReceiveMSGEvent(byte[] msgBuff)
        {
            ModbusTCP_ADU adu = new ModbusTCP_ADU();
            adu.MBAP.TransactionIDFrist = msgBuff[0];
            adu.MBAP.TransactionIDSecond = msgBuff[1];
            adu.MBAP.ProtocolIDFrist = msgBuff[2];
            adu.MBAP.ProtocolIDSecond = msgBuff[3];
            adu.MBAP.LengthFrist = msgBuff[4];
            adu.MBAP.LengthSecond = msgBuff[5];
            adu.MBAP.NetID = msgBuff[6];
            adu.FunctionCode = (ModbusFunctionCodes)msgBuff[7];
            byte[] data = new byte[msgBuff[8]];
            for (int i = 9, j = 0; j < msgBuff[8]; i++, j++)
            {
                data[j] = msgBuff[i];
            }
            adu.Data = data;

            //将接受数据帧存入对应的事务中
            try
            {
                ModbusTCPTransactionContorl.Instance.SetResponseADU(adu);
                ModbusTCPTransaction T = ModbusTCPTransactionContorl.Instance.GetTransactionByTransactionId((adu.MBAP.TransactionIDFrist << 8) + adu.MBAP.TransactionIDSecond);
                TransactionCompleteEvent(T);
                ModbusTCPTransactionContorl.Instance.RemoveTransaction((adu.MBAP.TransactionIDFrist << 8) + adu.MBAP.TransactionIDSecond);
            }
            catch (Exception ex)
            {
                ModbusTCPTransactionContorl.Instance.ReInit();

                ModbusTCPTransactionContorl.Instance.SetResponseADU(adu);
                ModbusTCPTransaction T = ModbusTCPTransactionContorl.Instance.GetTransactionByTransactionId((adu.MBAP.TransactionIDFrist << 8) + adu.MBAP.TransactionIDSecond);
                TransactionCompleteEvent(T);
                ModbusTCPTransactionContorl.Instance.RemoveTransaction((adu.MBAP.TransactionIDFrist << 8) + adu.MBAP.TransactionIDSecond);

            }

            //SocketClinet.DisConnect();
            //if ((adu.MBAP.TransactionIDFrist << 8) + adu.MBAP.TransactionIDSecond == 0x4AC)
            //{
            //    SocketClinet.DisConnect();
            //}

        }

        /// <summary>
        /// 写单个寄存器
        /// </summary>
        /// <param name="OutAddress">对方地址</param>
        /// <param name="OutValue">值</param>
        /// <param name="TransactionID">会话ID</param>
        public void WriteSingleRegister(UInt16 OutAddress, UInt16 OutValue, int TransactionID)
        {
            ModbusTCP_ADU adu = new ModbusTCP_ADU();

            byte TransactionIDFrist = 0;
            byte TransactionIDSecond = 0;

            if (TransactionID > 255)
            {
                TransactionIDFrist = (byte)(TransactionID >> 8);
                TransactionIDSecond = (byte)(TransactionID << 8 >> 8);
            }
            else
                TransactionIDSecond = (byte)(TransactionID);

            ModbusTCPMBAP MBAP = new ModbusTCPMBAP();
            MBAP.TransactionIDFrist = TransactionIDFrist;
            MBAP.TransactionIDSecond = TransactionIDSecond;
            MBAP.LengthFrist = 0;
            MBAP.LengthSecond = 6;
            MBAP.NetID = 1;

            adu.MBAP = MBAP;
            adu.FunctionCode = ModbusFunctionCodes.WriteSingleRegister;

            byte OutAddressFrist = 0;
            byte OutAddressSecond = 0;

            if (OutAddress > 255)
            {
                OutAddressFrist = (byte)(OutAddress >> 8);
                OutAddressSecond = (byte)(OutAddress << 8 >> 8);
            }
            else
                OutAddressSecond = (byte)(OutAddress);

            byte OutValueFrist = 0;
            byte OutValueSecond = 0;
            if (OutValue > 255)
            {
                OutValueFrist = (byte)(OutValue >> 8);
                OutValueSecond = (byte)(OutValue << 8 >> 8);
            }
            else
                OutValueSecond = (byte)(OutValue);

            byte[] Data = {OutAddressFrist,
                              OutAddressSecond,
                              OutValueFrist,
                              OutValueSecond
                          };

            adu.Data = Data;
            SocketClinet.SendMsg(adu.getADUBytes());
            //初始化一个事务
            ModbusTCPTransaction T = new ModbusTCPTransaction();
            T.TransactionID = TransactionID;
            T.RequestADU = adu;
            //将事务转交给事务管理器
            try
            {
                ModbusTCPTransactionContorl.Instance.AddTransaction(T);
            }
            catch (Exception ex)
            {
                ModbusTCPTransactionContorl.Instance.ReInit();
                ModbusTCPTransactionContorl.Instance.AddTransaction(T);
            }

        }

        /// <summary>
        /// 读取输入离散量
        /// </summary>
        /// <param name="startAddress">起始地址</param>
        /// <param name="byteCount">字节数</param>
        public void ReadInputDiscretions(UInt16 startAddress, UInt16 byteCount, int TransactionID)
        {
            ModbusTCP_ADU adu = new ModbusTCP_ADU();

            byte TransactionIDFrist = 0;
            byte TransactionIDSecond = 0;

            if (TransactionID > 255)
            {
                TransactionIDFrist = (byte)(TransactionID >> 8);
                TransactionIDSecond = (byte)(TransactionID << 8 >> 8);
            }
            else
                TransactionIDSecond = (byte)(TransactionID);

            ModbusTCPMBAP MBAP = new ModbusTCPMBAP();
            MBAP.TransactionIDFrist = TransactionIDFrist;
            MBAP.TransactionIDSecond = TransactionIDSecond;
            MBAP.LengthFrist = 0;
            MBAP.LengthSecond = 6;
            MBAP.NetID = 1;



            adu.MBAP = MBAP;
            adu.FunctionCode = ModbusFunctionCodes.ReadDiscretionsInput;
            byte startAddressFrist = 0;
            byte startAddressSecond = 0;

            if (startAddress > 255)
            {
                startAddressFrist = (byte)(startAddress >> 8);
                startAddressSecond = (byte)(startAddress << 8 >> 8);
            }
            else
                startAddressSecond = (byte)(startAddress);

            byte byteCountFrist = 0;
            byte byteCountSecond = 0;
            if (byteCount > 255)
            {
                byteCountFrist = (byte)(byteCount >> 8);
                byteCountSecond = (byte)(byteCount << 8 >> 8);
            }
            else
                byteCountSecond = (byte)(byteCount);

            byte[] Data = {startAddressFrist,
                              startAddressSecond,
                              byteCountFrist,
                              byteCountSecond
                          };

            adu.Data = Data;
            SocketClinet.SendMsg(adu.getADUBytes());
            //初始化一个事务
            ModbusTCPTransaction T = new ModbusTCPTransaction();
            T.TransactionID = TransactionID;
            T.RequestADU = adu;
            //将事务转交给事务管理器
            try
            {
                ModbusTCPTransactionContorl.Instance.AddTransaction(T);
            }
            catch (Exception ex)
            {
                ModbusTCPTransactionContorl.Instance.ReInit();
                ModbusTCPTransactionContorl.Instance.AddTransaction(T);
            }
        }







    }
}
